#pragma once

#include <cstdint>
#include<iostream>
#include <memory>
#include <openssl/types.h>
#include<string>
#include<functional>
#include"InetAddr.hpp"

// #include"EpollServer.hpp"

class Reactor;

//描述所有的链接(普通和listenfd)可以用继承分开写
class Connection
{
public:
    Connection():_sockfd(-1),_events(0)
    {}

    //设置sockfd
    void SetSockfd(int sockfd)
    {
        _sockfd = sockfd;
    }
    //设置文件文件描述符所对应epoller模型的回调指针
    void SetOwner(Reactor*owner)
    {
        _owner = owner;
    }
    //向外提供回调指针
    Reactor* GetOwner()
    {
        return _owner;
    }

    //设置远端信息
    void SetPeerInfo(const InetAddr &peer_addr)
    {
        _peer_addr = peer_addr;
    }
    //将读消息放入读缓冲区
    void Append(const std::string &in)
    {
        _inbuffer += in;//把收到的数据加到自己的缓冲区中
    }
    //将应答放入写缓冲区
    void Append2Out(const std::string &out)
    {
        _outbuffer += out;
    }
    //对外写缓冲区
    const std::string &OutString()
    {
        return _outbuffer;
    }
    //对外读缓冲区
    std::string &InBuffer()//故意取引用，是协议Decode时拿到完整报文后会移除该报文，进行缓冲区修改
    {
        return _inbuffer;
    }
    //对外sockfd
    int Fd()
    {
        return _sockfd;
    }
    //删除已写的字节
    void DisCardOutString(int n)
    {
        _outbuffer.erase(0, n);
    }
    //写缓冲区为空？
    bool IsOutBufferEmpty() {return _outbuffer.empty();}
    
    void SetEvents(uint32_t events) {_events = events;}

    uint32_t GetEvents() {return _events;}
    
    ~Connection()
    {}

    //回调方法
    virtual void Recver() = 0;
    virtual void Sender() = 0;
    virtual void Excepter() = 0;

protected:
    int _sockfd;
    std::string _inbuffer;  //输入缓冲区
    std::string _outbuffer; //输出缓冲区
    InetAddr _peer_addr;    //远端信息

    //指向自己epoller的回指针
    Reactor *_owner;

    //关心的事件
    uint32_t _events;
};

// //构建Connection
// class Factory
// {
// public:
//     static std::shared_ptr<Connection> BuildConnection(int fd,uint32_t events,func_t r,func_t s,func_t e)
//     {
//         auto con = std::make_shared<Connection>(fd);
//         con->SetEvents(events);
//         con->InitCB(r, s,e);
//         return con;
//     }
// };